/**
 * @file    elog.h
 * @brief   EasyLogger核心头文件
 * @details 本文件定义了EasyLogger日志库的核心接口和数据结构，包括：
 *          - 日志级别定义和宏定义
 *          - 日志输出接口函数声明
 *          - 过滤器配置接口声明
 *          - 异步输出和缓冲输出接口声明
 *          - 初始化和控制接口声明
 */

#ifndef __ELOG_H__
#define __ELOG_H__

#include <elog_cfg.h>
#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>

#ifdef __cplusplus
extern "C" {
#endif

/* ---------------------------------------------- 日志级别定义 -------------------------------------------- */
#define ELOG_LVL_ASSERT                      0                  /* 断言级别 */
#define ELOG_LVL_ERROR                       1                  /* 错误级别 */
#define ELOG_LVL_WARN                        2                  /* 警告级别 */
#define ELOG_LVL_INFO                        3                  /* 信息级别 */
#define ELOG_LVL_DEBUG                       4                  /* 调试级别 */
#define ELOG_LVL_VERBOSE                     5                  /* 详细级别 */

/* ---------------------------------------------- 过滤器级别 ---------------------------------------------- */
#define ELOG_FILTER_LVL_SILENT               ELOG_LVL_ASSERT    /* 静默级别 */
#define ELOG_FILTER_LVL_ALL                  ELOG_LVL_VERBOSE   /* 全部级别 */

/* ---------------------------------------------- 系统参数 ------------------------------------------------ */
#define ELOG_LVL_TOTAL_NUM                   6                  /* 日志级别总数 */
#define ELOG_SW_VERSION                      "2.2.99"           /* EasyLogger版本号 */

/* ---------------------------------------------- 断言宏定义 ---------------------------------------------- */
#ifdef ELOG_ASSERT_ENABLE
    #define ELOG_ASSERT(EXPR)                                                 \
    if (!(EXPR))                                                              \
    {                                                                         \
        if (elog_assert_hook == NULL) {                                       \
            elog_a("elog", "(%s) has assert failed at %s:%ld.", #EXPR, __FUNCTION__, __LINE__); \
            while (1);                                                        \
        } else {                                                              \
            elog_assert_hook(#EXPR, __FUNCTION__, __LINE__);                  \
        }                                                                     \
    }
#else
    #define ELOG_ASSERT(EXPR)                    ((void)0);                 /* 断言功能禁用时的空实现 */
#endif

/* ---------------------------------------------- 日志输出宏 ---------------------------------------------- */
#ifndef ELOG_OUTPUT_ENABLE
    #define elog_raw(...)                                                   /* 原始输出（禁用） */
    #define elog_assert(tag, ...)                                           /* 断言日志（禁用） */
    #define elog_error(tag, ...)                                            /* 错误日志（禁用） */
    #define elog_warn(tag, ...)                                             /* 警告日志（禁用） */
    #define elog_info(tag, ...)                                             /* 信息日志（禁用） */
    #define elog_debug(tag, ...)                                            /* 调试日志（禁用） */
    #define elog_verbose(tag, ...)                                          /* 详细日志（禁用） */
#else /* ELOG_OUTPUT_ENABLE */

    #ifdef ELOG_FMT_USING_FUNC
    #define ELOG_OUTPUT_FUNC __FUNCTION__                                   /* 使用函数名 */
    #else
    #define ELOG_OUTPUT_FUNC NULL                                           /* 不使用函数名 */
    #endif

    #ifdef ELOG_FMT_USING_DIR
    #define ELOG_OUTPUT_DIR __FILE__                                        /* 使用文件路径 */
    #else
    #define ELOG_OUTPUT_DIR NULL                                            /* 不使用文件路径 */
    #endif

    #ifdef ELOG_FMT_USING_LINE
    #define ELOG_OUTPUT_LINE __LINE__                                       /* 使用行号 */
    #else
    #define ELOG_OUTPUT_LINE 0                                              /* 不使用行号 */
    #endif

    #define elog_raw(...)  elog_raw_output(__VA_ARGS__)                     /* 原始输出宏 */
    #if ELOG_OUTPUT_LVL >= ELOG_LVL_ASSERT
        #define elog_assert(tag, ...) \
                elog_output(ELOG_LVL_ASSERT, tag, ELOG_OUTPUT_DIR, ELOG_OUTPUT_FUNC, ELOG_OUTPUT_LINE, __VA_ARGS__)
    #else
        #define elog_assert(tag, ...)                                       /* 断言日志宏（禁用） */
    #endif /* ELOG_OUTPUT_LVL >= ELOG_LVL_ASSERT */

    #if ELOG_OUTPUT_LVL >= ELOG_LVL_ERROR
        #define elog_error(tag, ...) \
                elog_output(ELOG_LVL_ERROR, tag, ELOG_OUTPUT_DIR, ELOG_OUTPUT_FUNC, ELOG_OUTPUT_LINE, __VA_ARGS__)
    #else
        #define elog_error(tag, ...)                                        /* 错误日志宏（禁用） */
    #endif /* ELOG_OUTPUT_LVL >= ELOG_LVL_ERROR */

    #if ELOG_OUTPUT_LVL >= ELOG_LVL_WARN
        #define elog_warn(tag, ...) \
                elog_output(ELOG_LVL_WARN, tag, ELOG_OUTPUT_DIR, ELOG_OUTPUT_FUNC, ELOG_OUTPUT_LINE, __VA_ARGS__)
    #else
        #define elog_warn(tag, ...)                                         /* 警告日志宏（禁用） */
    #endif /* ELOG_OUTPUT_LVL >= ELOG_LVL_WARN */

    #if ELOG_OUTPUT_LVL >= ELOG_LVL_INFO
        #define elog_info(tag, ...) \
                elog_output(ELOG_LVL_INFO, tag, ELOG_OUTPUT_DIR, ELOG_OUTPUT_FUNC, ELOG_OUTPUT_LINE, __VA_ARGS__)
    #else
        #define elog_info(tag, ...)                                         /* 信息日志宏（禁用） */
    #endif /* ELOG_OUTPUT_LVL >= ELOG_LVL_INFO */

    #if ELOG_OUTPUT_LVL >= ELOG_LVL_DEBUG
        #define elog_debug(tag, ...) \
                elog_output(ELOG_LVL_DEBUG, tag, ELOG_OUTPUT_DIR, ELOG_OUTPUT_FUNC, ELOG_OUTPUT_LINE, __VA_ARGS__)
    #else
        #define elog_debug(tag, ...)                                        /* 调试日志宏（禁用） */
    #endif /* ELOG_OUTPUT_LVL >= ELOG_LVL_DEBUG */

    #if ELOG_OUTPUT_LVL == ELOG_LVL_VERBOSE
        #define elog_verbose(tag, ...) \
                elog_output(ELOG_LVL_VERBOSE, tag, ELOG_OUTPUT_DIR, ELOG_OUTPUT_FUNC, ELOG_OUTPUT_LINE, __VA_ARGS__)
    #else
        #define elog_verbose(tag, ...)                                      /* 详细日志宏（禁用） */
    #endif /* ELOG_OUTPUT_LVL == ELOG_LVL_VERBOSE */
#endif /* ELOG_OUTPUT_ENABLE */

/* ---------------------------------------------- 格式化索引 ---------------------------------------------- */
typedef enum {
    ELOG_FMT_LVL    = 1 << 0,                                              /* 日志级别 */
    ELOG_FMT_TAG    = 1 << 1,                                              /* 标签 */
    ELOG_FMT_TIME   = 1 << 2,                                              /* 当前时间 */
    ELOG_FMT_P_INFO = 1 << 3,                                              /* 进程信息 */
    ELOG_FMT_T_INFO = 1 << 4,                                              /* 线程信息 */
    ELOG_FMT_DIR    = 1 << 5,                                              /* 文件目录和名称 */
    ELOG_FMT_FUNC   = 1 << 6,                                              /* 函数名称 */
    ELOG_FMT_LINE   = 1 << 7,                                              /* 行号 */
} ElogFmtIndex;

#define ELOG_FMT_ALL    (ELOG_FMT_LVL|ELOG_FMT_TAG|ELOG_FMT_TIME|ELOG_FMT_P_INFO|ELOG_FMT_T_INFO| \
    ELOG_FMT_DIR|ELOG_FMT_FUNC|ELOG_FMT_LINE)                              /* 所有格式化选项 */

/* ---------------------------------------------- 数据结构定义 -------------------------------------------- */
/* 标签级别过滤器结构体 */
typedef struct {
    uint8_t level;                                                          /* 过滤级别 */
    char tag[ELOG_FILTER_TAG_MAX_LEN + 1];                                  /* 标签名称 */
    bool tag_use_flag;                                                      /* 标签使用标志 */
} ElogTagLvlFilter, *ElogTagLvlFilter_t;

/* 日志过滤器结构体 */
typedef struct {
    uint8_t level;                                                          /* 过滤级别 */
    char tag[ELOG_FILTER_TAG_MAX_LEN + 1];                                  /* 过滤标签 */
    char keyword[ELOG_FILTER_KW_MAX_LEN + 1];                               /* 过滤关键字 */
    ElogTagLvlFilter tag_lvl[ELOG_FILTER_TAG_LVL_MAX_NUM];                  /* 标签级别过滤器数组 */
} ElogFilter, *ElogFilter_t;

/* EasyLogger主结构体 */
typedef struct {
    ElogFilter filter;                                                      /* 日志过滤器 */
    size_t enabled_fmt_set[ELOG_LVL_TOTAL_NUM];                             /* 各级别启用的格式化选项 */
    bool init_ok;                                                           /* 初始化完成标志 */
    bool output_enabled;                                                    /* 输出使能标志 */
    bool output_lock_enabled;                                               /* 输出锁使能标志 */
    bool output_is_locked_before_enable;                                    /* 使能前锁定状态 */
    bool output_is_locked_before_disable;                                   /* 禁用前锁定状态 */

#ifdef ELOG_COLOR_ENABLE
    bool text_color_enabled;                                                /* 文本颜色使能标志 */
#endif

}EasyLogger, *EasyLogger_t;

/* 错误代码枚举 */
typedef enum {
    ELOG_NO_ERR,                                                            /* 无错误 */
} ElogErrCode;

/* ---------------------------------------------- 核心函数声明 -------------------------------------------- */
ElogErrCode elog_init(void);                                                /* 初始化EasyLogger */
void elog_deinit(void);                                                     /* 反初始化EasyLogger */
void elog_start(void);                                                      /* 启动日志输出 */
void elog_stop(void);                                                       /* 停止日志输出 */
void elog_set_output_enabled(bool enabled);                                 /* 设置输出使能状态 */
bool elog_get_output_enabled(void);                                         /* 获取输出使能状态 */
void elog_set_text_color_enabled(bool enabled);                             /* 设置文本颜色使能 */
bool elog_get_text_color_enabled(void);                                     /* 获取文本颜色使能状态 */
void elog_set_fmt(uint8_t level, size_t set);                               /* 设置格式化选项 */
void elog_set_filter(uint8_t level, const char *tag, const char *keyword);  /* 设置过滤器 */
void elog_set_filter_lvl(uint8_t level);                                    /* 设置过滤级别 */
void elog_set_filter_tag(const char *tag);                                  /* 设置过滤标签 */
void elog_set_filter_kw(const char *keyword);                               /* 设置过滤关键字 */
void elog_set_filter_tag_lvl(const char *tag, uint8_t level);               /* 设置标签过滤级别 */
uint8_t elog_get_filter_tag_lvl(const char *tag);                           /* 获取标签过滤级别 */
void elog_raw_output(const char *format, ...);                              /* 原始输出函数 */
void elog_output(uint8_t level, const char *tag, const char *file, const char *func,
        const long line, const char *format, ...);                         /* 格式化输出函数 */
void elog_output_lock_enabled(bool enabled);                                /* 设置输出锁使能 */
extern void (*elog_assert_hook)(const char* expr, const char* func, size_t line); /* 断言钩子函数指针 */
void elog_assert_set_hook(void (*hook)(const char* expr, const char* func, size_t line)); /* 设置断言钩子 */
int8_t elog_find_lvl(const char *log);                                      /* 查找日志级别 */
const char *elog_find_tag(const char *log, uint8_t lvl, size_t *tag_len);   /* 查找日志标签 */
void elog_hexdump(const char *name, uint8_t width, const void *buf, uint16_t size); /* 十六进制转储 */

/* ---------------------------------------------- 简化API定义 -------------------------------------------- */
#define elog_a(tag, ...)     elog_assert(tag, __VA_ARGS__)                 /* 断言日志简化宏 */
#define elog_e(tag, ...)     elog_error(tag, __VA_ARGS__)                  /* 错误日志简化宏 */
#define elog_w(tag, ...)     elog_warn(tag, __VA_ARGS__)                   /* 警告日志简化宏 */
#define elog_i(tag, ...)     elog_info(tag, __VA_ARGS__)                   /* 信息日志简化宏 */
#define elog_d(tag, ...)     elog_debug(tag, __VA_ARGS__)                  /* 调试日志简化宏 */
#define elog_v(tag, ...)     elog_verbose(tag, __VA_ARGS__)                /* 详细日志简化宏 */

/* ---------------------------------------------- 全局标签API -------------------------------------------- */
/**
 * 全局标签API简化定义
 * 注意：使用log_x API之前必须先定义LOG_TAG和LOG_LVL宏
 */
#if !defined(LOG_TAG)
    #define LOG_TAG          "NO_TAG"                                       /* 默认标签名称 */
#endif
#if !defined(LOG_LVL)
    #define LOG_LVL          ELOG_LVL_VERBOSE                               /* 默认日志级别 */
#endif
#if LOG_LVL >= ELOG_LVL_ASSERT
    #define log_a(...)       elog_a(LOG_TAG, __VA_ARGS__)                   /* 全局断言日志宏 */
#else
    #define log_a(...)       ((void)0);                                     /* 断言日志宏（禁用） */
#endif
#if LOG_LVL >= ELOG_LVL_ERROR
    #define log_e(...)       elog_e(LOG_TAG, __VA_ARGS__)                   /* 全局错误日志宏 */
#else
    #define log_e(...)       ((void)0);                                     /* 错误日志宏（禁用） */
#endif
#if LOG_LVL >= ELOG_LVL_WARN
    #define log_w(...)       elog_w(LOG_TAG, __VA_ARGS__)                   /* 全局警告日志宏 */
#else
    #define log_w(...)       ((void)0);                                     /* 警告日志宏（禁用） */
#endif
#if LOG_LVL >= ELOG_LVL_INFO
    #define log_i(...)       elog_i(LOG_TAG, __VA_ARGS__)                   /* 全局信息日志宏 */
#else
    #define log_i(...)       ((void)0);                                     /* 信息日志宏（禁用） */
#endif
#if LOG_LVL >= ELOG_LVL_DEBUG
    #define log_d(...)       elog_d(LOG_TAG, __VA_ARGS__)                   /* 全局调试日志宏 */
#else
    #define log_d(...)       ((void)0);                                     /* 调试日志宏（禁用） */
#endif
#if LOG_LVL >= ELOG_LVL_VERBOSE
    #define log_v(...)       elog_v(LOG_TAG, __VA_ARGS__)                   /* 全局详细日志宏 */
#else
    #define log_v(...)       ((void)0);                                     /* 详细日志宏（禁用） */
#endif

#if !defined(assert)
    #define assert           ELOG_ASSERT                                    /* 标准断言宏重定义 */
#endif

/* ---------------------------------------------- 缓冲输出函数 -------------------------------------------- */
/* elog_buf.c */
void elog_buf_enabled(bool enabled);                                        /* 启用/禁用缓冲输出 */
void elog_flush(void);                                                      /* 刷新缓冲区 */

/* ---------------------------------------------- 异步输出函数 -------------------------------------------- */
/* elog_async.c */
void elog_async_enabled(bool enabled);                                      /* 启用/禁用异步输出 */
size_t elog_async_get_log(char *log, size_t size);                          /* 获取异步日志 */
size_t elog_async_get_line_log(char *log, size_t size);                     /* 获取异步行日志 */

/* ---------------------------------------------- 工具函数 ------------------------------------------------ */
/* elog_utils.c */
size_t elog_strcpy(size_t cur_len, char *dst, const char *src);             /* 字符串复制 */
size_t elog_cpyln(char *line, const char *log, size_t len);                 /* 复制日志行 */
void *elog_memcpy(void *dst, const void *src, size_t count);                /* 内存复制 */

#ifdef __cplusplus
}
#endif

#endif /* __ELOG_H__ */
